--------------------------------------------------------------------------------
--      Copyright (c) 2015 , 蒙占志(topameng) topameng@gmail.com
--      All rights reserved.
--      Use, modification and distribution are subject to the "MIT License"
--------------------------------------------------------------------------------

local sqrt = Mathf.Sqrt
local setmetatable = setmetatable
local rawset = rawset
local rawget = rawget
local clamp = Mathf.Clamp
local acos = math.acos

local Vector2Ex = {}
local get = tolua.initget(Vector2Ex)

local pool = nil
function Vector2Ex.SetPool(_pool)
	pool = _pool
end

--[[
new obj functions:
New
Clone
Normalize
__div(/)
__mul(*)
__add(+)
__sub(-)
__unm(-)



no new obj property:
up
right
zero
one
--]]


Vector2Ex.__index = function(t,k)
	local var = rawget(Vector2Ex, k)
	
	if var == nil then							
		var = rawget(get, k)
		
		if var ~= nil then
			return var(t)
		end
	end
	
	return var
end



function Vector2Ex._New(x, y)
	local v = {x = x or 0, y = y or 0}
	setmetatable(v, Vector2Ex)	
	return v
end

local _oldNew = Vector2Ex._New

function Vector2Ex.New(x, y)
	if pool then
		local c = pool:Create()
		c:Set(x, y)
		return c
	else
		return _oldNew(x, y)
	end
end

local _new = Vector2Ex.New

Vector2Ex.__call = function(t, x, y)
	return _new(x, y)
end

function Vector2Ex.Recycle(t)
	if pool then
		pool:Recycle(t)
	end
end



function Vector2Ex:Set(x,y)
	self.x = x or 0
	self.y = y or 0	
end

function Vector2Ex:Get()
	return self.x, self.y
end

function Vector2Ex:SqrMagnitude()
	return self.x * self.x + self.y * self.y
end

function Vector2Ex:Clone()
	return _new(self.x, self.y)
end

function Vector2Ex:Normalize()
	local v = self:Clone()
	return v:SetNormalize()	
end

function Vector2Ex:SetNormalize()
	local num = self:Magnitude()	
	
	if num == 1 then
		return self
    elseif num > 1e-05 then    
        self:Div(num)
    else    
        self:Set(0,0)
	end 

	return self
end

function Vector2Ex.Dot(lhs, rhs)
	return lhs.x * rhs.x + lhs.y * rhs.y
end

function Vector2Ex.Angle(from, to)
	local f = from:Normalize()
	local t = to:Normalize()
	local angle = acos(clamp(Vector2Ex.Dot(f, t), -1, 1)) * 57.29578
	f:Recycle()
	t:Recycle()
	return angle
end


function Vector2Ex.Magnitude(v2)
	return sqrt(v2.x * v2.x + v2.y * v2.y)
end

function Vector2Ex:Div(d)
	self.x = self.x / d
	self.y = self.y / d	
	
	return self
end

function Vector2Ex:Mul(d)
	self.x = self.x * d
	self.y = self.y * d
	
	return self
end

function Vector2Ex:Add(b)
	self.x = self.x + b.x
	self.y = self.y + b.y
	
	return self
end

function Vector2Ex:Sub(b)
	self.x = self.x - b.x
	self.y = self.y - b.y
	
	return
end

Vector2Ex.__tostring = function(self)
	return string.format("[%f,%f]", self.x, self.y)
end

Vector2Ex.__div = function(va, d)
	return _new(va.x / d, va.y / d)
end

Vector2Ex.__mul = function(va, d)
	return _new(va.x * d, va.y * d)
end

Vector2Ex.__add = function(va, vb)
	return _new(va.x + vb.x, va.y + vb.y)
end

Vector2Ex.__sub = function(va, vb)
	return _new(va.x - vb.x, va.y - vb.y)
end

Vector2Ex.__unm = function(va)
	return _new(-va.x, -va.y)
end

Vector2Ex.__eq = function(va,vb)
	return va.x == vb.x and va.y == vb.y
end

-- get.up 		= function() return Vector2Ex.New(0,1) end
-- get.right	= function() return Vector2Ex.New(1,0) end
-- get.zero	= function() return Vector2Ex.New(0,0) end
-- get.one		= function() return Vector2Ex.New(1,1) end

Vector2Ex.up 	= _new(0,1)
Vector2Ex.right	= _new(1,0)
Vector2Ex.zero	= _new(0,0)
Vector2Ex.one	= _new(1,1)

get.magnitude 		= Vector2Ex.Magnitude
get.normalized 		= Vector2Ex.Normalize
get.sqrMagnitude 	= Vector2Ex.SqrMagnitude

UnityEngine.Vector2Ex = Vector2Ex
setmetatable(Vector2Ex, Vector2Ex)
return Vector2Ex